package com.gameShare.service.user

import com.gameShare.entity.dto.game.GameCollectionDto
import com.gameShare.entity.dto.user.UserCollectionFolderDto
import com.gameShare.entity.vo.PageVo
import com.gameShare.enums.misc.ResponseCodeEnum
import com.gameShare.enums.user.UserActionEnum
import com.gameShare.enums.user.UserCollectionPermissionEnum
import com.gameShare.exceptions.BusinessException
import com.gameShare.mappers.user.UserCollectionMapper
import org.springframework.stereotype.Service

@Service
class UserCollectionService(
    private val userCollectionMapper: UserCollectionMapper,
    private val userActionService: UserActionService
) {


    /**
     * 创建收藏夹
     *
     * @param folderName 收藏夹名字
     * @param userId 用户id
     * @param permission 权限
     * @return 是否成功
     */
    fun createCollectionFolder(folderName : String, userId : String, permission: Int?): Boolean {
        checkCollectionFolderNameExist(userId, folderName)

        return( userCollectionMapper.createCollectionFolder(
                folderName,
                userId,
                permission ?: UserCollectionPermissionEnum.PUBLIC.code
            ) == 1
        )
    }

    /**
     * 删除收藏夹
     *
     * @param userId
     * @param collectionFolderId
     * @return 是否成功
     */
    fun delCollectionFolder(userId: String, collectionFolderId: Int ): Boolean {
        checkUserCanVisitCollection(userId, collectionFolderId)
        // 减少收藏数量
        userActionService.updateUserActionCount(
            userId,
            UserActionEnum.COLLECTION.code,
            -1 * userCollectionMapper.selectGameCountInCollection(collectionFolderId)
        )
        return userCollectionMapper.deleteCollectionFolder(collectionFolderId) == 1
    }

    /**
     * 改变收藏信息
     *
     * @param name 名字
     * @param permission 文件夹权限
     * @param userId 用户id
     * @param collectionFolderId 收藏夹id
     * @return 是否成功
     */
    fun changeCollectionFolderInfo(name : String? ,permission: Int?, userId: String, collectionFolderId: Int ): Boolean {
        if (name == null && permission == null)
            return false
        name ?: throw BusinessException(ResponseCodeEnum.ARGUMENT_ERROR)
        if (name.isEmpty()) throw BusinessException(ResponseCodeEnum.ARGUMENT_ERROR)
        checkCollectionFolderNameExist(userId, name)

        checkUserCanVisitCollection(userId, collectionFolderId)
        return userCollectionMapper.updateCollectionFolderName(name, permission,collectionFolderId) == 1
    }


    /**
     * 加入游戏进入文件夹内
     * @param gameId
     * @param userId
     * @param collectionFolderId
     * @return 是否成功
     */
    fun addGameToCollection(gameId : String, userId : String, collectionFolderId : Int): Boolean {
        // 用户鉴权
        checkUserCanVisitCollection(userId, collectionFolderId)
        // 判断是否已经存在游戏
        if (userCollectionMapper.checkGameInCollectionExist(gameId, collectionFolderId) == 1)
            throw BusinessException(ResponseCodeEnum.INFO_EXIST.code, "游戏已在文件夹内")
        return userCollectionMapper.addGameToCollectionFolder(gameId, collectionFolderId) == 1.also {
            userActionService.updateUserActionCount(userId, UserActionEnum.COLLECTION.code, 1)
        }
    }


    /**
     * 删除收藏夹的游戏
     *
     * @param gameId 游戏id
     * @param userId 用户id
     * @param collectionFolderId 收藏夹id
     * @return 是否成功
     */
    fun delGameInCollection(gameId: String, userId: String, collectionFolderId: Int): Boolean {
        // 用户鉴权
        checkUserCanVisitCollection(userId, collectionFolderId)
        return userCollectionMapper.deleteGameInCollectionFolder(gameId) == 1.also {
            userActionService.updateUserActionCount(userId, UserActionEnum.COLLECTION.code, -1)
        }
    }


    /**
     * 加载一个文件夹内所有的游戏dto
     *
     * @param pageNo 页码
     * @param pageSize 页面大小
     * @param userId 访问用户id
     * @param collectionFolderId 收藏夹id
     * @return 用户收藏dto分页对象
     */
    fun loadGamePageInCollection(
        pageNo : Int?,
        pageSize : Int?,
        userId: String,
        collectionFolderId: Int
    ): PageVo<GameCollectionDto?> {
        checkUserCanVisitCollection(userId, collectionFolderId)
        if (userCollectionMapper.selectGameCollectionUser(collectionFolderId) != userId &&
            userCollectionMapper.selectCollectionFolderPermission(collectionFolderId) == UserCollectionPermissionEnum.PRIVATE.code
        )
            throw BusinessException(ResponseCodeEnum.ARGUMENT_ERROR)
        return PageVo.generatePageVo(
            pageNo, pageSize,
            {
                userCollectionMapper.selectGameCountInCollection(
                    collectionFolderId
                )
            },
            {start, end ->  userCollectionMapper.selectCollectionGamesByPage(collectionFolderId, start, end)}
        )
    }

    /**
     * 加载用户所有收藏夹
     *
     * @param targetUserId 目标用户id
     * @param visitUserId 被访问的用户id
     * @return 是否成功
     */
    fun loadAllCollectionFolder(targetUserId : String, visitUserId : String): List<UserCollectionFolderDto> {
        return if (targetUserId != visitUserId){
            // 如果访问id与被访问id不同则只允许返回公有的
            userCollectionMapper.selectUserAllFolder(targetUserId, UserCollectionPermissionEnum.PUBLIC.code)
        } else userCollectionMapper.selectUserAllFolder(targetUserId, null)
    }


    /**
     * 检查用户是否能够编辑文件夹通过userId
     *
     * @param userId 用户id
     * @param collectionFolderId 收藏文件夹id
     */
    private fun checkUserCanVisitCollection(userId: String, collectionFolderId : Int){
        if (userCollectionMapper.checkCollectionFolderExist(collectionFolderId) == 0)
            throw BusinessException(ResponseCodeEnum.ARGUMENT_ERROR)
        if (userCollectionMapper.selectGameCollectionUser(collectionFolderId) != userId)
            throw BusinessException(ResponseCodeEnum.ARGUMENT_ERROR)
    }

    /**
     * 检查用户收藏夹是否存在文件夹名字
     *
     * @param userId 用户id
     * @param folderName 文件夹名
     */
    private fun checkCollectionFolderNameExist(userId: String, folderName: String){
        if (userCollectionMapper.selectUserCollectionNames(userId)?.contains(folderName) == true)
            throw BusinessException(ResponseCodeEnum.INFO_EXIST.code, "收藏夹名字存在")
    }

}